package com.andy.basics;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.model.DataModel;

import org.springframework.beans.factory.annotation.Autowired;

public abstract class Controller<T extends Entity> {

	private boolean error;

	private Utils utils;

	private HttpUtil httpUtil;

	private GenericDao genericDao;

	private MessageHandler messageHandler;

	private Validator validator;

	private List<String> errors = new ArrayList<String>();

	public abstract T create();

	public abstract Service<T> getService();

	public void save(final T t) {
		this.getService().save(t);
	}

	public List<T> findAll() {
		List<T> list = this.getService().findAll();
		return list == null ? new ArrayList<T>(0) : list;
	}

	public List<T> getAll() {
		return this.findAll();
	}

	public T getModel() {
		if (this.getService().getModel() == null) {
			this.getService().setModel(this.create());
			System.out.println("Creating new...");
		}
		return this.getService().getModel();
	}

	public String submit() {
		return null;
	}

	public String add() {
		if (this.getValidator().validate(this.getModel(), this.getMessageHandler())) {
			if (this.validate(this.getModel(), this.getMessageHandler())) {
				this.save(this.getModel());
				this.reset();
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public String remove() {
		try {
			this.getService().remove((T) this.getData().getRowData());
			this.reset();
		} catch (Exception e) {
			this.getMessageHandler().addMessage(
					"newmsg",
					this.utils.getRootCause(e) instanceof SQLException ? "Delete not permitted for this " + this.getModelName()
							+ ", This entity is being referenced !" : e.getMessage());
		}
		return null;
	}

	public String update() {
		this.getService().update(this.getModel());
		return null;
	}

	public String cancel() {
		this.reset();
		return null;
	}

	public void reset() {
		this.getService().setModel(null);
		this.getService().setEditing(false);
		this.setError(false);
	}

	public boolean isEditing() {
		return this.getService().isEditing();
	}

	@SuppressWarnings("unchecked")
	public String select() {
		Object obj = this.getData().getRowData();
		System.out.println(obj + "" + this.getData().getRowIndex());
		this.setModel((T) this.getData().getRowData());
		this.getService().setEditing(true);
		return null;
	}

	public void setModel(final T model) {
		this.getService().setModel(model);
	}

	public DataModel getData() {
		return this.getService().getDataModel();
	}

	public String getModelName() {
		return "Entity";
	}

	@Autowired
	public void setMessageHandler(final MessageHandler messageHandler) {
		this.messageHandler = messageHandler;
	}

	public MessageHandler getMessageHandler() {
		return this.messageHandler;
	}

	@Autowired
	public void setUtils(final Utils utils) {
		this.utils = utils;
	}

	public Utils getUtils() {
		return this.utils;
	}

	@Autowired
	public void setValidator(final Validator validator) {
		this.validator = validator;
	}

	public Validator getValidator() {
		return this.validator;
	}

	protected boolean validate(final T model, final MessageHandler handler) {
		return true;
	}

	public void setErrors(final List<String> errors) {
		this.errors = errors;
	}

	public List<String> getErrors() {
		return this.errors;
	}

	public void setError(final boolean error) {
		this.error = error;
	}

	public boolean isError() {
		return this.error;
	}

	@Autowired
	public void setGenericDao(final GenericDao genericDao) {
		this.genericDao = genericDao;
	}

	public GenericDao getGenericDao() {
		return this.genericDao;
	}

	@Autowired
	public void setHttpUtil(final HttpUtil httpUtil) {
		this.httpUtil = httpUtil;
	}

	public HttpUtil getHttpUtil() {
		return this.httpUtil;
	}

	public void setDate(final Date date) {
		this.getModel().setDate(date);
	}

	public Date getDate() {
		return new Date();
	}

	public void setVacate(String eatUpThisString) {
	}

	public String getVacate() {
		return null;
	}
}
